﻿using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;

namespace Notoric.View.Music.CWNotation.Controls
{
    /// <summary>
    /// Visualizes a flag.
    /// </summary>
    public partial class Flag : UserControl
    {
        #region Constructors

        /// <summary>
        /// Creates a new <see cref="Flag"/> instance.
        /// </summary>
        public Flag()
        {
            InitializeComponent();
        }

        #endregion

        #region Event Handlers

        /// <summary>
        /// Occurs when the data context (visualized flag) has changed.
        /// </summary>
        /// <remarks>
        /// <b>Operation:</b><br/>
        /// The handler unbinds from the old flag's <see cref="ViewModel.ViewModelElement.PropertyChanged"/>, 
        /// caches the new visualized flag, binds to its <see cref="ViewModel.ViewModelElement.PropertyChanged"/> event
        /// and calls <see cref="SetVisualization"/>.
        /// </remarks>
        /// <param name="sender">Object where the event handler is attached</param>
        /// <param name="e">Event data</param>
        private void UserControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            if (flag != null)
                flag.PropertyChanged -= flag_PropertyChanged;

            flag = (ViewModel.Elements.CWNotation.Flag)DataContext;

            if (flag != null)
                flag.PropertyChanged += new PropertyChangedEventHandler(flag_PropertyChanged);

            SetVisualization();
        }

        /// <summary>
        /// Occurs when the contol has been loaded.
        /// </summary>
        /// <remarks>
        /// <b>Operation:</b><br/>
        /// The handler caches the visualized flag, binds to its <see cref="ViewModel.ViewModelElement.PropertyChanged"/> event
        /// and calls <see cref="SetVisualization"/>.
        /// </remarks>
        /// <param name="sender">Object where the event handler is attached</param>
        /// <param name="e">Event data</param>
        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            flag = (ViewModel.Elements.CWNotation.Flag)DataContext;

            if (flag != null)
                flag.PropertyChanged += new PropertyChangedEventHandler(flag_PropertyChanged);

            SetVisualization();
        }

        /// <summary>
        /// Occurs when the value of some of the flag's properties has changed.
        /// </summary>
        /// <remarks>
        /// <b>Operation:</b><br/>
        /// If the modified property is <see cref="Notoric.ViewModel.Elements.CWNotation.Flag.IsLast"/>
        /// or <see cref="Notoric.ViewModel.Elements.CWNotation.Flag.Orientation"/> the handler calls the <see cref="SetVisualization"/> method.
        /// </remarks>
        /// <param name="sender">Object that has sent the event</param>
        /// <param name="e">Event data</param>
        private void flag_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "IsLast" || e.PropertyName == "Orientation")
                SetVisualization();
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Selects the symbol and margin that correspond
        /// to the visualized flag.
        /// </summary>
        private void SetVisualization()
        {
            if (flag == null)
                PART_FlagSymbol.Text = "";

            var staffSpaces = flag.FindOwner<ViewModel.Elements.CWNotation.Staff>().Lines.Count - 1;
            var spaceSize = (staffSpaces > 0 ? flag.FindOwner<ViewModel.Elements.CWNotation.Chord>().EffectiveTypeSize / staffSpaces : flag.FindOwner<ViewModel.Elements.CWNotation.Staff>().SpaceSize);

            if (flag.Orientation == ViewModel.Elements.CWNotation.StemOrientation.Up)
            {
                if (flag.IsLast)
                {
                    PART_FlagSymbol.Text = "j";
                    PART_FlagSymbol.Margin = new Thickness(-spaceSize - 0.78, -2 * spaceSize, 0, 0);
                }
                else
                {
                    PART_FlagSymbol.Text = "û";
                    PART_FlagSymbol.Margin = new Thickness(-spaceSize - 0.78, -4.75 * spaceSize, 0, 0);
                }
            }
            else
            {
                if (flag.IsLast)
                {
                    PART_FlagSymbol.Text = "J";
                    PART_FlagSymbol.Margin = new Thickness(0, -9 * spaceSize, 0, 0);
                }
                else
                {
                    PART_FlagSymbol.Text = "ð";
                    PART_FlagSymbol.Margin = new Thickness(-0.38, -6.25 * spaceSize, 0, 0);
                }
            }
        }

        #endregion

        #region Private Fields

        /// <summary>
        /// Holds the visualized flag.
        /// </summary>
        private ViewModel.Elements.CWNotation.Flag flag;

        #endregion
    }
}
